; (function ($) {
    var g = {
        mousePos: { x: 0, y: 0 }
    }; //全局定义
    var help = {
        getSelectionStart: function () {
            var node = document.getSelection().anchorNode;
            return node ? (node.nodeType == 3 ? node : node) : undefined;
        }
    }; //帮助类

    function Field(element, options) {
        var self = this;
        this.elem = element;
        this.config = $.extend(true, {}, $.fn.field.defaults, element.data(), options);
        this.init();
    };

    /**
     **列表组件的初始化
     **/
    Field.prototype.init = function () {
        var _this = this;
        _this.concrate();
        _this.initConfig();


        //注册事件；
        $(document).bind('mousemove', function (evt) {
            g.mousePos.x = evt.pageX;
            g.mousePos.y = evt.pageY;
        });

        _this.elem.click(function (e) {
            g.mousePos.x = e.pageX;
            g.mousePos.y = e.pageY;
        });

        _this.elem.keydown(function (e) {
            var targetNode = help.getSelectionStart();
            if (targetNode != undefined && targetNode.nodeType === 1 && targetNode.nodeName == 'SPAN') {
                if (targetNode.className == 'deco-text') {
                    if (e.keyCode == 8) {
                        var _t = $(targetNode);
                        if (_t.text().length == 0) {
                            var _p = _t.prev();
                            if (_p.length == 0) {
                                if (_p.parent().hasClass('ndp-field-wrapper')) {
                                    e.stopImmediatePropagation();
                                    e.preventDefault();
                                }
                            } else {
                                if (_p.hasClass('deco-tag')) {
                                    _p.remove();
                                }
                            }
                        } else if (_t.text().length == 1) {
                            e.stopImmediatePropagation();
                            e.preventDefault();
                            _t.text('');
                        }
                    }
                } else if (targetNode.className == 'deco-tag' || $(targetNode).parents(".deco-tag").length) {
                    e.stopImmediatePropagation();
                    e.preventDefault();
                    if (e.keyCode == 8) {//删除
                        if ($(targetNode).hasClass("deco-close")) targetNode = targetNode.parentNode;
                        var range = document.createRange();
                        range.selectNode(targetNode);
                        var sel = window.getSelection();
                        sel.removeAllRanges();
                        sel.addRange(range);
                        document.execCommand("delete", false, null);
                    }
                }
            }

        });

        _this.elem.keyup(function (e) {
            _this.elem.find(".deco-tag").attr('contenteditable', 'false');
        })
    };

    Field.prototype.tagListen = function () {
        _this = this;
        _this.elem.off("click", ".deco-tag>.deco-close").on("click", ".deco-tag>.deco-close", function () {
            var range = document.createRange();
            var sel = window.getSelection();
            range.setStart($(this).parent().prev()[0], 0);
            range.collapse(true);
            sel.removeAllRanges();
            sel.addRange(range);
            $(this).parent().next().remove();
            $(this).parent().remove();
        });
    }
    /**
     ** 构建
     **/
    Field.prototype.concrate = function () {
        _this = this;
        _this.elem.attr({ tabindex: "-1", contenteditable: "true", spellcheck: "false" });
        if (!_this.elem.html().length) {
            _this.elem.html("<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'></span>")
        }
    };

    /***
     ** 处理用户设置配置
     ***/
    Field.prototype.initConfig = function () {

    }

    /**
     * jquery 提供了一个objct 即 fn，which is a shotcut of jquery object prototype
     * or you can call it jquery plugin shell  == fn
     *  类似于  Class.prototype.jqplugin = function(){};0
     *  the   $.fn  [same as] Class.prototype
     * plugin entrance
     */
    $.fn.field = function (options) {
        var the = this.first();
        var field = new Field(the, options);
        the = $.extend(true, {}, the, new exchange(field));
        return the;
    };
    /***
     **和其他插件的交互
     ** factory Class
     **@param {Page} page :  instacne of the plugin builder
     **/
    function exchange(field) {

        /***
         **@param {Object} o={val:值,text:显示的内容}
         ***/
        this.addTag = function (o) {
            var targetNode = help.getSelectionStart();
            if (targetNode.className == 'deco-text') {
                var _t = $(targetNode);
                var n = _t.html();
                var tag = "<span class='deco-tag' contenteditable='false' spell-check='false' data-val='" + o.val + "' >" +
                    "<span class='deco-close'>&times;</span>" + o.text + "</span><span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + field.config.space + "</span>";

                document.execCommand("insertHTML", false, tag);
                n = _t.html();
                var s = n.indexOf('<');
                var e = n.lastIndexOf('>');
                var _pre = "";
                var _suffix = "";
                var mS = 0;
                var mE = n.length;
                if (s > -1) {
                    _pre = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + n.substring(0, s) + "</span>";
                    mS = s;
                } else {
                    if (n.length) {
                        mS = n.length;
                        _pre = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + n.substring(0, n.length) + "</span>";
                    }
                }
                if (e > -1) {
                    if (e < mE - 1) {
                        _suffix = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + n.substring(e + 1) + "</span>";
                        var spaceTS = n.lastIndexOf('<span');
                        //如果已经有一个text了
                        if (n.indexOf('deco-text', spaceTS) > -1) {
                            mE = spaceTS;
                        } else {
                            mE = e + 1;
                        }
                    } else {
                        mE = e + 1;
                    }
                }

                var _m = n.substring(mS, mE);
                var _r = _pre + _m + _suffix;
                _t.replaceWith(_r);
            } else {
                var tag = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'></span><span class='deco-tag' contenteditable='false' spell-check='false' data-val='" + o.val + "' >" +
                    "<span class='deco-close'>&times;</span>" + o.text + "</span><span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + field.config.space + "</span>";
                document.execCommand("insertHTML", false, tag);
            }
            field.elem.find(".deco-tag").attr('contenteditable', 'false');

            field.tagListen();
            return field.elem;
        };



        this.addTxt = function (txt) {
            var targetNode = help.getSelectionStart();
            if (targetNode == undefined) {
                return;
            }
            if (targetNode.className == 'deco-text') {
                var _t = $(targetNode);
                var n = _t.html();
                var tag = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + field.config.space + "</span><span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + txt + "</span><span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + field.config.space + "</span>";

                document.execCommand("insertHTML", false, tag);
                n = _t.html();
                var s = n.indexOf('<');
                var e = n.lastIndexOf('>');
                var _pre = "";
                var _suffix = "";
                var mS = 0;
                var mE = n.length;
                if (s > -1) {
                    _pre = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + n.substring(0, s) + "</span>";
                    mS = s;
                } else {
                    if (n.length) {
                        mS = n.length;
                        _pre = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + n.substring(0, n.length) + "</span>";
                    }
                }
                if (e > -1) {
                    if (e < mE - 1) {
                        _suffix = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + n.substring(e + 1) + "</span>";
                        var spaceTS = n.lastIndexOf('<span');
                        //如果已经有一个text了
                        if (n.indexOf('deco-text', spaceTS) > -1) {
                            mE = spaceTS;
                        } else {
                            mE = e + 1;
                        }
                    } else {
                        mE = e + 1;
                    }
                }

                var _m = n.substring(mS, mE);
                var _r = _pre + _m + _suffix;
                _t.replaceWith(_r);
            } else {
                var tag = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + field.config.space + "</span><span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + txt + "</span><span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + field.config.space + "</span>";
                document.execCommand("insertHTML", false, tag);
            }

            var targetNode = help.getSelectionStart();
            if (targetNode) {
                var range = document.createRange();
                var sel = window.getSelection();
                range.setStart(document.getSelection().anchorNode, document.getSelection().baseOffset);
                range.collapse(true);
                sel.removeAllRanges();
                sel.addRange(range);
            }

            field.tagListen();
            return field.elem;
        }

        /**
         * 添加 emoji 方法专用, txt 显示 ,val 提交为字符
         */
        this.addEmoji = function (txt, val) {
            var targetNode = help.getSelectionStart();
            if (targetNode == undefined) {
                return;
            }
            if (targetNode.className == 'deco-text' || targetNode.parentNode.className == 'deco-text') {
                var isParent = false;
                if (targetNode.parentNode.className == 'deco-text') {
                    targetNode = targetNode.parentNode;
                    isParent = true;
                }

                var _t = $(targetNode).first();
                var n = _t.html();
                var tag = "<span class='deco-emoji' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + txt + "</span><span class='deco-text' style='display:none;min-width:1px;height:24px;line-height:24px;'>" + val + "</span><span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + field.config.space + "</span>";

                document.execCommand("insertHTML", false, tag);
                if (!isParent) {
                    n = _t.html();
                    var s = n.indexOf('<');
                    var e = n.lastIndexOf('>');
                    var _pre = "";
                    var _suffix = "";
                    var mS = 0;
                    var mE = n.length;
                    if (s > -1) {
                        _pre = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + n.substring(0, s) + "</span>";
                        mS = s;
                    } else {
                        if (n.length) {
                            mS = n.length;
                            _pre = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + n.substring(0, n.length) + "</span>";
                        }
                    }
                    if (e > -1) {
                        if (e < mE - 1) {
                            _suffix = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + n.substring(e + 1) + "</span>";
                            var spaceTS = n.lastIndexOf('<span');
                            //如果已经有一个text了
                            if (n.indexOf('deco-text', spaceTS) > -1) {
                                mE = spaceTS;
                            } else {
                                mE = e + 1;
                            }
                        } else {
                            mE = e + 1;
                        }
                    }

                    var _m = n.substring(mS, mE);
                    var _r = _pre + _m + _suffix;
                    _t.replaceWith(_r);
                } else {
                    targetNode.outerHTML = $(targetNode).html();
                }
            } else {
                var tag = "<span class='deco-emoji' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + txt + "</span><span class='deco-text' style='display:none;min-width:1px;height:24px;line-height:24px;'>" + val + "</span><span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'>" + field.config.space + "</span>";

                document.execCommand("insertHTML", false, tag);
            }

            var targetNode11 = help.getSelectionStart();
            if (targetNode11) {
                var range = document.createRange();
                var sel = window.getSelection();
                range.setStart(targetNode11, document.getSelection().baseOffset);
                range.collapse(true);
                sel.removeAllRanges();
                sel.addRange(range);
            }

            field.tagListen();
            return field.elem;
        }


        /****
         ***
         ****/
        this.setContent = function (str) {

        }
        /***
         **  获得输入的数据
         ***/
        this.getContent = function () {
            var clone = field.elem.clone();
            clone.find("span.deco-space").remove();
            clone.find("span.deco-close").remove();
            clone.find("span.deco-emoji").remove();
            clone.find("span.deco-tag").each(function (index, item) {
                var the = $(item);
                var val = the.data("val");
                var txt = the.text().trim();
                the.replaceWith("{{" + val + "|" + txt + "}}");
            });
            clone.find("span.deco-text").each(function (index, item) {
                var the = $(item);
                var txt = the.text();
                the.replaceWith(txt);
            });
            clone.children("div").prepend("#b#n");
            return clone.text();
        };



        /***
         ** 用户把数据回填到这里，显示相应的格式
         **@param {String} str 字符串数据
         ***/
        this.fill = function (strs, isOverWrite) {
            var arr = [];
            var pre = "";
            if(!!strs){
                arr = strs.split("#b#n");
            }
            if (!isOverWrite) {
                pre = String(field.elem.html()).trim();
            }
            var cont = pre;
            if (!cont.length) {
                cont += "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'></span>";
            }
            var x = "<span class='deco-close'>&times;</span>";
            for (var i = 0; i < arr.length; i++) {
                var str = arr[i];
                str = $.trim(str);
                var nstr = str.replace(/\{\{(.+?)\|(.+?)\}\}/ig, function (all, p1, p2) {
                    var ctx = "<span class='deco-tag' contenteditable='false' data-val=" + p1 + ">" + x + p2.trim() + "</span>" +
                        "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'></span>";
                    return ctx;
                });

                if (i > 0) {
                    nstr = "<span class='deco-text' style='display:inline-block;min-width:1px;height:24px;line-height:24px;'></span>" + nstr;
                    nstr = "<div>" + nstr + "</div>";
                }
                cont += nstr;
            }
            field.elem.html(cont);
            field.tagListen();
            return field.elem;
        };

        /****
         ** 删除 tag
         ****/
        this.removeTag = function () {

        };
    }

    var old = $.fn.field;
    $.fn.field.Constructor = Field;
    // page NO CONFLICT
    // ===============
    $.fn.field.noConflict = function () {
        $.fn.field = old;
        return this;
    }
    /***
     ** outside accessible default setting
     **/
    $.fn.field.defaults = {
        space: '&nbsp;'
    };
}(jQuery));
